const {ccclass, property} = cc._decorator;

interface KeyPoint {
    coor: cc.Vec2;
    covered: boolean;
    debugNode?: cc.Node,
}
@ccclass
export default class DrawBase extends cc.Component {
    @property(cc.Mask)
    mask: cc.Mask = null;
    @property
    keyPointDistance = 20; //隔10px生成一个关键点
    @property
    strokeWidth = 20;//画笔宽度
    @property
    throttleRate = 10; //节流程度 
    @property
    finishJudgeValue = 0.9;//画完判定 超过这个值就算完成了

    @property(cc.Label)
    finishRate: cc.Label = null;

    @property
    judgeMarginW = 0; //判定点生成margin 不能大于宽的1/2

    @property
    judgeMarginH = 0; //判定点生成margin 不能大于高的1/2

    @property
    debug = false;


    graphics: cc.Graphics;

    keyPoints: KeyPoint[][] = []

    _drawing = false;
    _loc: cc.Vec2;

    //插值用
    _lastLoc: cc.Vec2;
    _drawLineDis = 5;

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {}

    start() {
        cc.debug.setDisplayStats(true);
        //@ts-ignore
        this.graphics = this.mask._graphics;
        cc.log(this.graphics)

        this.reset();
        this.generateKeyPoints();

        let throttleMark = 0;
        this.node.on(cc.Node.EventType.TOUCH_START, e => {
            let locSpace = e.getLocation();
            let localLoc = this.mask.node.convertToNodeSpaceAR(locSpace);
            this.graphics.moveTo(localLoc.x, localLoc.y)
            this._drawing = true;
            this._lastLoc = localLoc;
        })

        this.graphics.lineWidth = this.strokeWidth;


        this.node.on(cc.Node.EventType.TOUCH_MOVE, e => {
            let locSpace = e.getLocation();
            let localLoc = this.mask.node.convertToNodeSpaceAR(locSpace);
            this.drawLine(localLoc);
            // }
        })


        this.node.on(cc.Node.EventType.TOUCH_END, e => {
            this._drawing = false;
            let done = this.checkKeyPoints();
            cc.log(done)
            if (done) {
                // alert('done!')
            }
        })
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, e => {
            this._drawing = false;
        })
    }

    drawLine(localLoc) {
        if (localLoc.x > -this.mask.node.width / 2 && localLoc.x < this.mask.node.width / 2 && localLoc.y > -this.mask.node.height / 2 && localLoc.y < this.mask.node.height / 2) {

            this.graphics.circle(localLoc.x, localLoc.y, this.strokeWidth / 2)
            this.graphics.fill();


            if (this._lastLoc) {
                let _dis = cc.Vec2.distance(localLoc, this._lastLoc);
                cc.log(_dis)
                if (_dis > this._drawLineDis) {
                    this.graphics.moveTo(this._lastLoc.x, this._lastLoc.y);
                    this.graphics.lineTo(localLoc.x, localLoc.y);
                    this.graphics.stroke();
                    this._lastLoc = localLoc;
                }
            }
            this.updateKeyPoints(localLoc);
        } else {
            this.graphics.moveTo(localLoc.x, localLoc.y);
        }
    }

    draw(localLoc) {
        if (localLoc.x > -this.mask.node.width / 2 && localLoc.x < this.mask.node.width / 2 && localLoc.y > -this.mask.node.height / 2 && localLoc.y < this.mask.node.height / 2) {
            // this.graphics.lineTo(localLoc.x, localLoc.y)
            // this.graphics.stroke();

            this.graphics.circle(localLoc.x, localLoc.y, this.strokeWidth / 2)
            this.graphics.fill();

            if (this._lastLoc) {
                let deltaX = (localLoc.x - this._lastLoc.x) / 2
                let deltaY = (localLoc.y - this._lastLoc.y) / 2
                this.graphics.circle(localLoc.x + deltaX, localLoc.y + deltaY, this.strokeWidth / 2)
                // this.graphics.circle(localLoc.x + deltaX * 2, localLoc.y + deltaY * 2, this.strokeWidth / 2)
                // this.graphics.circle(localLoc.x + deltaX * 3, localLoc.y + deltaY * 3, this.strokeWidth / 2)
                this.graphics.fill();
            }
            this._lastLoc = localLoc;

            this.updateKeyPoints(localLoc);
        } else {
            this.graphics.moveTo(localLoc.x, localLoc.y);
        }
    }

    reset() {
        this.graphics.clear();
        this.graphics.strokeColor = cc.color(255, 255, 255);
        this.graphics.lineWidth = this.strokeWidth;
        this.keyPoints = [];
    }

    //更新关键点
    updateKeyPoints(loc: cc.Vec2) {


        let row = Math.round((loc.y + (this.mask.node.height- this.judgeMarginH) / 2) / this.keyPointDistance);
        let col = Math.round((loc.x + (this.mask.node.width - this.judgeMarginW) / 2) / this.keyPointDistance);
        let offset = 0;

        //画笔宽度比判定点间隔大的情况
        if (this.strokeWidth > this.keyPointDistance) {
            offset = Math.floor(this.strokeWidth / 2 / this.keyPointDistance);
        }


        if (offset > 0) {
            // cc.log('stroke larger than keyPointDistance', offset)
            for (let i = -offset; i < offset; i++) {
                for (let j = -offset; j < offset; j++) {
                    let p = this.keyPoints[row + i] ? this.keyPoints[row + i][col + j] : null;
                    p && (p.covered = true);
                    if (this.debug) {
                        p && (p.debugNode.color = cc.color(0, 255, 0))
                    }
                }

            }
        } else {
            let p = this.keyPoints[row] ? this.keyPoints[row][col] : null;
            p && (p.covered = true);
            if (this.debug) {
                p && (p.debugNode.color = cc.color(0, 255, 0))
            }
        }
        if (this.debug) {
            this.checkKeyPoints();
        }
    }

    //检测完成
    checkKeyPoints() {
        let total = this.keyPoints.length * this.keyPoints[0].length;
        let done = this.keyPoints.reduce((pre, cur) => {
            return cur.reduce((_p, _c) => {
                return _p + (_c.covered ? 1 : 0);
            }, pre);
        }, 0)
        let rate = done / total;
        if (this.debug) {
            cc.log(rate);
            this.finishRate.string = `${done}/${total} :${rate.toFixed(2)}`;
        }
        return rate >= this.finishJudgeValue
    }

    //根据图片分辨率自动生成关键点  默认图片大小和mask大小一致  用于判定画图进度
    generateKeyPoints() {
        let {width, height} = this.mask.node;
        width -= this.judgeMarginW;
        height -= this.judgeMarginH;
        this.keyPoints = [];
        let cols = Math.round((width) / this.keyPointDistance);
        let rows = Math.round((height) / this.keyPointDistance);
        for (let r = 0; r < rows; r++) {
            if (!this.keyPoints[r])
                this.keyPoints[r] = [];

            for (let c = 0; c < cols; c++) {
                let point: KeyPoint = {
                    coor: cc.v2(c * this.keyPointDistance - width / 2 + this.keyPointDistance / 2, r * this.keyPointDistance - height / 2 - this.keyPointDistance / 2),
                    covered: false
                }
                if (this.debug) {
                    let _n = new cc.Node();
                    let _l = _n.addComponent(cc.Label);
                    _l.fontSize = 10;
                    _n.color = cc.color(255, 0, 0);
                    _l.string = `0`
                    point.debugNode = _n;
                    this.node.getChildByName('debugNode').addChild(_n);
                    _n.x = point.coor.x;
                    _n.y = point.coor.y;
                }
                this.keyPoints[r].push(point)
            }
        }
    }
}
